//
// Created by dqchen on 2022/12/12.
//

#include "symtab.h"
#include "symbol.h"

void Symtab::addVar(Var *v) {
    vector<Var *> *vec = var_map[v->getName()];
    if(vec){
        vec->push_back(v);
    } else{
        var_map[v->getName()] = new vector<Var *>;
        var_map[v->getName()]->push_back(v);
    }
    var_seq.push_back(v->getName());

}

void Symtab::addFunc(Func *f) {
    func = f;
    string name = f->getName();
    if (func_map.find(name) != func_map.end()) {
        printf("Duplicate func [%s]\n", name.c_str());
    } else{
        func_map[name] = f;
        func_seq.push_back(name);
    }

}

vector<int>& Symtab::getScope(){
    return scope_seq;

}

Symtab::Symtab() {
    scope_seq.push_back(0);
    func = nullptr;
}

Symtab::~Symtab() {
}

Var *Symtab::getVar(string name) {
    if (var_map.find(name) != var_map.end()) {
        vector<Var *> *vec = var_map[name];
        //暂不考虑变量作用域的问题，直接取第一个
        return vec->front();
    }
    return nullptr;
}

Func *Symtab::getFunc(string name) {
    if (!(func_map.find(name) != func_map.end())) return nullptr;
    return func_map[name];
}

Func *Symtab::getCurFunc() {
    return !func ? new Func() : func;
}

void Symtab::incScope() {
    scope_seq.push_back(0);
}

void Symtab::decScope() {
    scope_seq.pop_back();
    func = nullptr;
}

void Symtab::addOrder(Order *order) {
    if(func){
        func->addOrder(order);
    } else{
        delete order;
    }
}

void Symtab::initGen(OrderGenerator *gen) {
    this->generator = gen;
}

vector<Var *> Symtab::getStrs() {
    return str_seq;
}

vector<string> Symtab::getFuncSeq() {
    return func_seq;
}

void Symtab::addStrSeq(Var *v) {
    str_seq.push_back(v);
}

void Symtab::addExtern(string name) {
    if(name == "mem" || name == "mfr"){//暂时只支持内存分配和释放的外部函数
        for (string n: extern_seq){
            if (name == n) {
                return;
            }
        }
        extern_seq.push_back(name);
    }
}

vector<string> Symtab::getExternSeq() {
    return extern_seq;
}

void Symtab::addGlobalVar(Var *v) {
    string key = v->getStructType() != "" ? v->getStructType() : v->getName();
    vector<Var *> *vec = global_var_map[key];
    if(vec){
        vec->push_back(v);
    } else{
        global_var_map[key] = new vector<Var *>;
        global_var_map[key]->push_back(v);
    }

}

Var *Symtab::getGlobalVar(string name) {
    if (global_var_map.find(name) != global_var_map.end()) {
        vector<Var *> *vec = global_var_map[name];
        //暂不考虑变量作用域的问题，直接取第一个
        return vec->front();
    }
    return nullptr;
}
